没看完 您所在的位置:网站首页 perl opendir函数 没看完

没看完

2024-05-09 04:38| 来源: 网络整理| 查看: 265

这一篇是搬过来的,原来的在这儿http://www.freeoa.net/development/perl/perl-mod-file-find_2114.html

尊重他人劳动成果,感谢!

 

它是Perl核心模块之一,用于文件的搜索及查找。Perl之中的File::Find模块对在整个文件系统中搜索文件名十分有用,特别是你可以使用正则来匹配文件名并循环地穿过任何的目录结构(许可情况下)。为了展示它的工作方式,我将给出一个使用File::Find模块的脚本实例。

语法: use File::Find; find(\&wanted, @directories_to_search); sub wanted { ... }

 use File::Find; find({ wanted => \&process, follow => 1 }, '.');

File::Find的两个方法:find 是自上而下遍历。

finddepth 是自下而上遍历。二者调用格式相同,上例中 finddepth(\&del_svn, "."),第一个参数是调用的子函数,第二个参数是根目录。

这里简单的说一下 find 函数,find 函数的用法如下:find(\&wanted, @directories_to_search);

find()函数包含两个参数,子程序的引用和目录列表。第一个参数是一个代码的引用或者是一个hash引用对于每个文件。

其中第一个参数 wanted 是个子函数,也就是回调函数,由你自己来定义,这个参数必须有,即使它的内容为空。第二个参数是个目录列表,一般情况下,我们可能只是处理一个目录,所以它也可以是个普通的表示目录名的字串标量。

需要注意的是,&wanted 子程序的前面需要加一反斜杠转义。

与文件及其路径相关的三个属性:$File::Find::dir 是当前目录全路径。$_ 是当前文件名(不含路径)。$File::Find::name 是当前文件的完整路径。

$File::Find::dir is the current directory name,$_ is the current filename within that directory$File::Find::name is the complete pathname to the file.

 以文件'/some/path/foo.ext '为例:$File::Find::dir  = /some/path/$_  = foo.ext$File::Find::name = /some/path/foo.ext

File::Find的属性在使用过程中,可以设置其具体属性来改变其行为,最终得到想要结果。find(\%options, @directories);

finddepth(\%options, @directories);

其实上面所提及的wanted函数,就是这个%options中的最重要的key了。

Perl脚本可以寻找以.tmp, .chk或是.zip结尾的文件或是以~符号开始的文件来完成,脚本将输出它找到的每一个文件的完整路径,而且在最后会显示出所占用的字节数。

在标准Perl库和Perl函数中设置了一个模块,因此当你的机器上安装了Perl之后,所有必要的模块就都可以使用了,File::Find函数模仿了UNIX的find命令并将穿过一个文件树。这里是此方式的API: Find(&yoursubroutine, ‘dir1’, ‘dir2’…); 

提供的子程序,将在后面详细叙述,还有希望进行搜索的目录的列表,记住这些目录将以一种深度优先方式被穿过,使用的另一个方式就是stat()函数(与C的同名库函数类似)。

File::Find方式具有特殊变量,将被赋予特定的信息,显示如下: * $_包含目录中的当前文件名 * $File::Find::dir包含当前目录名 * $File::Find::name包含$File::Find::dir/$_ 

当子程序被调用时,就会确实位于变量$File::Find::dir的目录中,子程序使用常规表达式来与$_匹配,$_使用一个if声明来寻找我们前面详细给出的所有文件名。 

如果在$_之中存储的文件名与if声明中的五个常规表达式中的任何一个相匹配,我们就将在其下面输入代码块,常规表达式非常的简单,“.”代表一个文字上的点号而不是常规表达式中的“.”的特殊意义,我们使用“”符号来避开特殊意义。“$”代表一个字符串最后的匹配而“^”代表与开头匹配。下表显示了我们试图将其与相对应的常规表达式相匹配的文件。 File that ends with .zip     /.zip$/ File that ends with .tmp     /.tmp$/ File that ends with .TMP     /.TMP$/ File that begins with ~     /^~/ File that ends with .chk     /.chk/ 

注意:脚本对小写的tmp和大写的TMP同时进行查找,而出于效率方面的考虑,可以将文件名改为大写并只查找TMP匹配。 

最后,脚本使用stat()函数来记录所有与if声明之中的某个条件相匹配的文件所使用的字节数。如果条件符合,脚本将存储$size之中的值并将其加入到$ByteCount记录变量,如下面的代码所示: $ByteCount += $size; 

perl下的File::Find模块具有shell下的find命令的功能,下面具体看2个例子: 

1、找出某个目录下面以*.old结尾的文件 use strict; use File::Find; my $path = '/home/test/'; sub wanted { if ( -f $File::Find::name ) {  if ( $File::Find::name =~ /\.old$/ ) {   print "$File::Find::name\n";   } }}find( \&wanted, $path ); 

2、找出某个目录下面几天前的文件 my $path = '/home/test/'; opendir DH, $path or die "cannot chdir to $path : $!"; for my $file (readdir DH) {  next if $file eq "." or $file eq "..";  next if $file =~ /^\./;  if (time() - (stat($path.$file))[8] > (60*60*24*7)) {   print $path.$file."\n";  } } closedir DH;

Perl中的find模块使用方式有以下几种:use File::Find; find(/&wanted, @directories_to_search); sub wanted { ... } 

use File::Find; finddepth(/&wanted, @directories_to_search); sub wanted { ... } 

use File::Find; find({ wanted => /&process, follow => 1 }, '.'); 

主要有两个函数,find和finddepth,这两个方法大致相同,但也有细微的差别: find: find(/&wanted,  @directories); find(/%options, @directories); find()会在@directories的参数所给定的目录中顺序的进行深度优先的查找,对于每一个找到的 文件 或者目录,都会调用&wanted引用所指向的sub(函数)。$wanted函数的具体使用见下文。 

另外,对于每一个找到的目录,它都会chdir()到这个目录内部,然后递归的在这个目录中 继续调用&wanted sub来操作这个目录下的子目录或文件。 

finddepth: finddepth(/&wanted,  @directories); finddepth(/%options, @directories); 

finddepth()函数的用法和find()几乎一样,只不过它会在查找完当前目录之后 ,再进入当前 目录的子目录中进行查找。它采用了后序遍历算法取代了前序遍历算法。 

wanted函数: 在wanted()函数中,可以对文件和目录做任何形式的判断和确认。需要注意的是:wanted() 函数实质上是一个回调函数,它的返回值被忽略。 wanted函数没有参数,但是会包含一系列的内部变量,如: $File::Find::dir     是当前目录的名字 $_     是当前正在处理的文件名 $File::Find::name     是当前文件的完整路径+文件名 

以上变量都已经被包含在wanted函数中,并且不会影响函数外的同名变量。 例如,如果要检查文件 /some/path/foo.ext ,这些变量的值就是: $File::Find::dir  = /some/path/ $_                = foo.ext $File::Find::name = /some/path/foo.ext 

程序运行时将会chdir()到$File::Find::dir目录中,除非没有子目录了。 

程序示例: sub wanted { /^/.nfs.*/z/s && (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) && int(-M _) > 7 && unlink($_) || ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) && $dev < 0 && ($File::Find::prune = 1); }

比较重要的参数有:wanted、bydepth、no_chdir

wanted它将指向一代码块,其中包含了对每一个找到的'项'和处理逻辑。

bydepth在将目录符合条件文件列表输出后,再输出该目录名。

no_chdir当置为'false'时,在其工作过程中,不进入(chdir)其所在的当前目录。下面是其默认、false、true三种情况的对比:             $File::Find::name  $File::Find::dir  $_ default      /                  /                 .  no_chdir=>0  /etc               /                 etc              /etc/x             /etc              x

 no_chdir=>1  /                  /                 /              /etc               /                 /etc              /etc/x             /etc              /etc/x

$find::Find::prune 可停止将find()函数移到该目录中use File::Find;find(\&wanted,'/root/bin');sub wanted{ #停止搜索sys目录 $File::Find::prune = 1 if /sys/; if (/\.log/i) {  print "FILE: $_\n";  print "Dir: $File::Find::dir\n";  print "Path: $File::Find::name\n"; }}

参考文档:File::Find



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有